package com.winit.deploy.util;

import com.alibaba.fastjson.JSONObject;
import com.winit.common.util.*;
import com.winit.core.server.base.ExecResultHandler;
import com.winit.core.server.linux.LinuxLocalServer;
import com.winit.deploy.bean.DeployEnum;
import com.winit.project.core.edition.PackageEditionConfig;
import com.winit.project.util.ProjectUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by wangjian on 16/9/9.
 */
public class DeployUtil {

    private static final Logger logger = LoggerFactory.getLogger(DeployUtil.class);

    public static final String RELEASE_PROJECT_DIR = ConfigUtil.getValue("rootPath")+"Beetle/release/project/";

    /**
     * 1.测试通过,将版本保存至release对应目录下
     * 2.发布staging/onling环境,记录并保存版本至release对应目录
     * 3.获取当前测试通过版本
     * 4.获取staging/online环境发布记录
     */

    public static synchronized boolean updateProjectVersion(String projectName
            ,String editionNum,DeployEnum deployEnum){
        logger.info("保存工程发版信息,projectName="+projectName+",editionNum="+editionNum+",deployEnum="+deployEnum.getDesc());
        if(StringUtils.isEmpty(projectName) || StringUtils.isEmpty(editionNum)){
            logger.error("保存工程发版信息,参数存在空值!");
            return false;
        }
        String fileName = projectName+"#"+editionNum;
        String dir = RELEASE_PROJECT_DIR+ ProjectUtil.getTrunkProjectName(projectName)+"/"+deployEnum.getDesc();
        File file = new File(dir);
        if(!file.exists()){
            file.mkdirs();
        }
        List<File> list = getFileList(dir);

        File newFile = new File(dir+"/"+fileName);
        try {
            if(list.size() > 0){
                if(fileName.equals(list.get(0).getName())){
                    return true;
                }
                for(int i= list.size()-1;i>=0;i--){
                    if(i<=3){
                        break;
                    }
                    ShellRunUtil.runCmds("rm","-rf",list.get(i).getAbsolutePath());
                }
            }
            if(newFile.exists()){
                ShellRunUtil.runCmds("rm","-rf",newFile.getAbsolutePath());
            }
            newFile.mkdirs();
            //拷贝war包
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date now = new Date();
            JSONObject object = new JSONObject();
            object.put("date",format.format(now));
            JSONFileUtil.saveFileJson(newFile.getAbsolutePath()+"/info.json",object);
            String editionPath = ProjectUtil.getProjectFilePath(projectName)+editionNum;
            String nasNum = ProjectUtil.getEditionNasNum(editionPath);

            StringBuffer fromPath = new StringBuffer();
            fromPath.append(editionPath).append("/target/");
            if(StringUtils.isEmpty(nasNum)){
                fromPath.append("*");
            }else {
                fromPath.append(nasNum).append("/*");
            }

            ShellRunUtil.runCmds("cp","-Rf",fromPath.toString(),newFile.getAbsolutePath()+"/");
            logger.info("保存工程发版信息,file="+newFile.getPath());
            return true;
        }catch (Exception e){
            logger.error("保存工程发版信息异常,file="+newFile.getPath(),e);
            return false;
        }
    }

    public static synchronized boolean delProjectVersion(String projectName
            ,String editionNum,DeployEnum deployEnum){
        logger.info("删除工程发版信息,projectName="+projectName+",editionNum="+editionNum+",deployEnum="+deployEnum.getDesc());
        if(StringUtils.isEmpty(projectName) || StringUtils.isEmpty(editionNum)){
            logger.error("删除工程发版信息,参数存在空值!");
            return false;
        }
        String fileName = RELEASE_PROJECT_DIR+ProjectUtil.getTrunkProjectName(projectName)
                +"/"+deployEnum.getDesc()+"/"+projectName+"#"+editionNum;
        File file = new File(fileName);
        if(file.exists()){
            ShellRunUtil.runCmds("rm","-rf",file.getAbsolutePath());
        }
        return true;
    }

    private static List<File> getVersionFileList(String trunkName,String deployEnum){
        String dir = RELEASE_PROJECT_DIR+trunkName+"/"+deployEnum;
        return getFileList(dir);
    }

    private static List<File> getFileList(String dir){
        File file = new File(dir);
        if(!file.exists()){
            file.mkdirs();
        }
        List<JSONObject> list = new ArrayList<>();
        for (File f:file.listFiles()){
            JSONObject object = JSONFileUtil.getFileJsonForBean(f.getAbsolutePath()+"/info.json",JSONObject.class);
            object.put("file",f);
            list.add(object);
        }
        Collections.sort(list,new Comparator<JSONObject>(){
            @Override
            public int compare(JSONObject o1, JSONObject o2) {
                Date a = o1.getDate("date");
                Date b = o2.getDate("date");
                return b.compareTo(a);
            }
        });

        List<File> l = new ArrayList<>();
        for (JSONObject object:list){
            l.add((File) object.get("file"));
        }
        return l;
    }

    public static String getProjectVersion(String trunkName, DeployEnum deployEnum, String type){
        logger.info("com.winit.deploy.util.DeployUtil.getProjectVersion trunkName="+trunkName+",deployEnum="+deployEnum.getDesc()
                +",type="+type);
        List<File> list = getVersionFileList(ProjectUtil.getTrunkProjectName(trunkName),deployEnum.getDesc());
        logger.info("com.winit.deploy.util.DeployUtil.getProjectVersion.getVersionFileList trunkName="+trunkName+",deployEnum="+deployEnum.getDesc()
                +",type="+type);
        if(list.size() == 0){
            return "";
        }
        if("projectName".equals(type)){
            return list.get(0).getName().split("#")[0];
        }else if("editionNum".equals(type)){
            return list.get(0).getName().split("#")[1];
        }else{
            return list.get(0).getName();
        }
    }

    /**
     * 获取发布备份时,备份文件名称
     * @param projectName
     * @return
     */
    public static String getBakFileName(String projectName){
        StringBuffer name = new StringBuffer();
        name.append(projectName).append("-").append(DateUtil.transDateToStr(new Date())).append(".tgz");
        return name.toString();
    }

    /**
     *线上环境发布成功后,拷贝当前的分支版本包到nas的指定目录下
     * @param projectName
     * @param editionNum
     * @return
     * @throws Exception
     */
    public static synchronized boolean cpOnlineVersionToNas(String projectName,String editionNum){
        String nas_dir = ConfigUtil.getValue("nas_latest_product");
        StringBuffer path = new StringBuffer();
        path.append(StringUtils.isEmpty(nas_dir)?"/mnt/build/latest.product":nas_dir)
                .append("/").append(ProjectUtil.getTrunkProjectName(projectName));
        //1、校验保存的目录是否存在
        File file = new File(path.toString());
        if(!file.exists()){
            file.mkdirs();
        }
        //2、版本信息文件是否存在  存在说明当前已经时这个版本  不需要重复拷贝
        String versionFile = path.toString()+"/"+projectName+"@"+editionNum+".version";
        File f = new File(versionFile);
        if(f.exists()){
            logger.info("com.winit.deploy.util.DeployUtil.cpOnlineVersionToNas 文件已存在.path="+versionFile);
            return true;
        }
        //3、先清空目录  然后touch version文件 拷贝war包
        try {
            ExecResultHandler handler = new ExecResultHandler();
            handler = LinuxLocalServer.getInstance().doExecRtnHandler("rm -rf "+path.toString()+"/*");
            if(!handler.isSuccess()){
                logger.error("com.winit.deploy.util.DeployUtil.cpOnlineVersionToNas 清空目录失败 path="+path.toString()+",desc="+handler.getMessage());
                return false;
            }
            handler = LinuxLocalServer.getInstance().doExecRtnHandler("touch "+versionFile);
            if(!handler.isSuccess()){
                logger.error("com.winit.deploy.util.DeployUtil.cpOnlineVersionToNas 创建版本文件失败 path="+versionFile+",desc="+handler.getMessage());
                return false;
            }
            StringBuffer cmd = new StringBuffer();
            PackageEditionConfig editionConfig = new PackageEditionConfig(projectName,editionNum,true);
            cmd.append("cp -R ").append(ProjectUtil.getEditionPath(projectName,editionNum)).append("/target/").append(editionConfig.getNasNum())
                    .append("/* ").append(path.toString()).append("/");
            handler = LinuxLocalServer.getInstance().doExecRtnHandler(cmd.toString());
            if(!handler.isSuccess()){
                logger.error("com.winit.deploy.util.DeployUtil.cpOnlineVersionToNas 拷贝war失败 cmd="+cmd.toString()+",desc="+handler.getMessage());
                if(f.exists()){
                    logger.info("com.winit.deploy.util.DeployUtil.cpOnlineVersionToNas 拷贝war失败,删除版本文件 path="+versionFile);
                    f.delete();
                }
                return false;
            }
        }catch (Exception e){
            logger.error("com.winit.deploy.util.DeployUtil.cpOnlineVersionToNas 拷贝异常 path="+versionFile,e);
            if(f.exists()){
                logger.info("com.winit.deploy.util.DeployUtil.cpOnlineVersionToNas 拷贝异常,删除版本文件 path="+versionFile);
                f.delete();
            }
            return false;
        }
        return true;
    }

    /**
     * 记录使用kill 停止的应用
     * @param projectName
     */
    public static synchronized void saveProjectWithKill(String projectName){
        logger.info("com.winit.deploy.util.DeployUtil.saveProjectWithKill projectName="+projectName);
        StringBuffer path = new StringBuffer();
        path.append(ConfigUtil.getValue("rootPath")).append("Beetle/release/log/log-").append(DateUtil.getCurDateStr("yyyyMMdd")).append(".log");
        FileUtil.writeLog(path.toString(),projectName);
    }
}
